(function($) {
    // bug fix for jquery validation 1.16.0
	if(jQuery.validator){
		jQuery.validator.prototype.resetInternals = function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = $( [] );
			this.toHide = $( [] );
			this.currentElements = $( [] );
		};
	}

	$.m.form = {
		version : "1.0",
		timeFormat : "yyyy-MM-dd HH:mm:ss",
		dateFormat : "yyyy-MM-dd",
		
		/**
		 * 表单元素回显
		 * name : 表单元素的name
		 * value : 需要回显的值
		 */
		initValue : function (name, value, containerId) {
			var $container = null;
			if(containerId == null){
				$container = $("body");
			} else if( containerId instanceof jQuery ){
				$container = containerId;
			} else {
				$container = $("#" + containerId);
			}
			//init input/textarea/select
			$container.find(":input[name='"+name+"']").not(":radio").not(":checkbox").val(value).change(); 
			//init radio
			var $radio = $container.find(":radio[name='"+name+"'][value='"+value+"']");
			$radio.attr("checked", true).parent("span").addClass("checked"); 
			$radio.parent("span").addClass("checked");
			$container.find(":radio[name='"+name+"']").not($radio).parent("span").removeClass("checked");
			if (value.length>0) {
			    var arr = value.split(',');
			    $.each(arr, function(index, val){
			        $("input[type=checkbox][name='"+name+"']").each(function () {
			            if($(this).val() == val) {
			                $(this).attr("checked",true);
			            }
			        });
			    });
			}
		},
		
		disable : function($ele){
			$ele.attr('disabled',"disabled");
		},
		
		enable : function($ele){
			$ele.removeAttr("disabled");
		},
		
		readonly : function($form, removeButton){
			var inputs = $form.find(":input");
	        inputs.not(":submit,:button").prop("readonly", true).prop("disabled",true);
	        if(removeButton) {
	            inputs.remove(":button,:submit");
	        }
	        $form.find("select,input:radio,input:checkbox").prop("disabled",true);
	        $form.find("span.required").hide(); //hide require tips
	        
	        $form.find("div.date button").prop("disabled",true).on("click", function(e){
	        	e.preventDefault();
	        });
		},
		
		reset : function($form){
			$form.find(":input") 
			 .not(':button, :submit, :reset, :hidden')  
			 .val('') 
			 .removeAttr('checked')  
			 .removeAttr('selected');
		},

		validate: function($form, config){
			// for more info visit the official plugin documentation:
            // http://docs.jquery.com/Plugins/Validation

			// Metronic vendors.bundle.js 里有默认初始化逻辑，这里配置就比较少了，详情见：
            // src/js/framework/components/plugins/forms/jquery-validation.init.js
	        var error = $('[data-role="alert-error"]', $form);
	        var success = $('[data-role="alert-success"]', $form);
	        var defaultConfig = {
	            invalidHandler: function (event, validator) { //display error alert on form submit              
					// show error alert
					success.addClass("d-none");
                    error.removeClass("d-none");
                    if(!$form.parents(".modal")[0]){
                        $.m.scrollTo(error, -200);
                    }
	            },
	            submitHandler: function (form) {
                    success.removeClass("d-none");
                    error.addClass("d-none");
	                form.submit();
	            }
	        }
            var validateConfig = $.extend(true, {}, defaultConfig, config ? config : {});
            $form.validate(validateConfig);

	        //apply validation on select2 dropdown value change, this only needed for chosen dropdown integration.
            $('.select2me', $form).change(function () {
            	$form.validate().element($(this)); //revalidate the chosen dropdown value and show error or success message for the input
            });

            //initialize datepicker
            if($.fn.datepicker){
            	/*$('.date-picker').datepicker({
            		autoclose: true
            	});*/
            	$('.date-picker .form-control').change(function() {
            		$form.validate().element($(this)); //revalidate the chosen dropdown value and show error or success message for the input 
            	})
            }
            
            // init server error
            $form.find("span.help-block-error").closest(".form-group").addClass("has-error");
		},
		

		initSelect : function($select, config) {
			config = config ? config : {};
			if(!config.getDisplayRepo){
				config.getDisplayRepo = function (repo){
					//text是多选时回显option里的值
					return repo.text || repo.name;
				}
			}
			$select.select2($.extend(true, {},{
				/*width: "auto",*/
				ajax : {
					dataType : 'json',
					delay : 250,
					data : function(params) {
						return {
							query : params.term, // search term
							page : params.page
						};
					},
					processResults : function(data, params) {
						// parse the results into the format expected by Select2
						// since we are using custom formatting functions we do
						// not need to
						// alter the remote JSON data, except to indicate that
						// infinite
						// scrolling can be used
						params.page = params.page || 1;

						return {
							results : data.items,
							pagination : {
								more : (params.page * 10) < data.totalCount
							}
						};
					},
					cache : true
				},
				escapeMarkup : function(markup) {
					return markup;
				},
				minimumInputLength : 0,
				templateResult : function(repo) {
					if (repo.loading)
						return repo.text;
					var htmls = [];
					htmls.push("<div>");
					htmls.push(config.getDisplayRepo(repo));
					htmls.push("</div>");
					return htmls.join('');
				},
				templateSelection : function(repo) {
					return config.getDisplayRepo(repo);
				},
				onSelect : function(e) {
					$select.find('option').attr('selected', 'selected');
				},
				onUnselect : function(e) {
					var id = e.params.data.id
					$select.find('option[value="' + id + '"]').remove();
				}
			}, config));
			
			$select.on("select2:open", function (e) { config.onOpen && config.onOpen.call(undefined, e) });
			$select.on("select2:close", function (e) { config.onClose && config.onClose.call(undefined, e) });
			$select.on("select2:select", function (e) { config.onSelect && config.onSelect.call(undefined, e) });
			$select.on("select2:unselect", function (e) { config.onUnselect && config.onUnselect.call(undefined, e) });
		},
		
		initMultiSelect : function($select, config){
			config = config || {};
			$('#roleIds').multiSelect({
		    	selectableHeader:$i18n.multiselect.unselectedItems,
		    	selectionHeader:$i18n.multiselect.selectedItems,
		    	selectableFooter:"333",
		    	selectionFooter:"444"
		    }).multiSelect("select", "[${(roleIds)!?join(',')}]");
		},
		
		initDualListbox : function($select, config){
			var defaultConfig = {
				filterTextClear: $.i18n.dualListbox.filterTextClear,
				filterPlaceHolder: $.i18n.dualListbox.filterPlaceHolder,
				moveSelectedLabel: $.i18n.dualListbox.moveSelectedLabel,
				moveAllLabel: $.i18n.dualListbox.moveAllLabel,
				removeSelectedLabel: $.i18n.dualListbox.removeSelectedLabel,
				removeAllLabel: $.i18n.dualListbox.removeAllLabel,
				infoText: $.i18n.dualListbox.infoText,
				infoTextFiltered: $.i18n.dualListbox.infoTextFiltered,
				infoTextEmpty: $.i18n.dualListbox.infoTextEmpty,
					
				nonSelectedListLabel: $.i18n.dualListbox.nonSelectedListLabel,
				selectedListLabel: $.i18n.dualListbox.selectedListLabel,
				preserveSelectionOnMove: 'moved',
				moveOnSelect: true,
				selectedData:{}
			}
			config = config || {};
			config = $.extend(true, {}, defaultConfig, config);
			$.each(config.selectedData, function(i,value){
				$select.find("option[value='"+value+"']").attr("selected", "selected");
			});
			$select.bootstrapDualListbox(config);
		},
		
		alert: function($form, options){
			if(!options) {
	            options = {};
	        }
			var message = ''; 
			var type = 'error';
	        if(typeof options === 'string'){
	        	message = options
	        } else {
	        	message = options.message;
	        	type = options.type;
	        }
	        var iconClass = options.type == 'error'?'fa fa-close':'fa fa-check';
	        var containerClass = options.type == 'error'?'alert-danger':'alert-success';
	        var template = '<div class="alert '+containerClass+' alertTips" data-close-in-seconds="3">'+
		        '<button type="button" class="close" data-dismiss="alert" ></button>'+
		        '<i class="'+iconClass+'"></i>&nbsp;'+ message +
		    '</div>';
	        $form.find("div.alertTips").remove();
	        $(template).insertBefore($form.find(".form-group").first());
		},
		
		alertError: function($form, message){
			$.m.form.alert($form, {
				type: 'error',
				message: message
			});
		},
		
		alertSuccess: function($form, message){
			$.m.form.alert($form, {
				type: 'success',
				message: message
			});
		},
		
		initDatePicker: function($container){
            var $container = $container ? $container : $("body");
			if($.fn.datepicker){
				$container.find('.date-picker').datepicker({
					//rtl: App.isRTL(),
                    format: "yyyy-mm-dd",
                    pickerPosition: "bottom-left",
					autoclose: true
				});
			}
			if($.fn.datetimepicker){
				$container.find(".form_datetime").datetimepicker({
		            autoclose: true,
		            //isRTL: App.isRTL(),
		            format: "yyyy-mm-dd hh:ii:ss",
                    pickerPosition: "bottom-left",
		        });

				$container.find(".form_advance_datetime").datetimepicker({
		            //isRTL: App.isRTL(),
		            format: "dd MM yyyy - hh:ii",
		            autoclose: true,
		            todayBtn: true,
		            startDate: "2013-02-14 10:00",
		            //pickerPosition: (App.isRTL() ? "bottom-right" : "bottom-left"),
		            minuteStep: 10
		        });

				$container.find(".form_meridian_datetime").datetimepicker({
		            //isRTL: App.isRTL(),
		            format: "dd MM yyyy - HH:ii P",
		            showMeridian: true,
		            autoclose: true,
		            //pickerPosition: (App.isRTL() ? "bottom-right" : "bottom-left"),
		            todayBtn: true
		        });
			}
			if ($.fn.timepicker) {
				$container.find('.timepicker-default').timepicker({
		            autoclose: true,
		            showSeconds: true,
		            minuteStep: 1
		        });

				$container.find('.timepicker-no-seconds').timepicker({
		            autoclose: true,
		            minuteStep: 5,
		            defaultTime: false
		        });

				$container.find('.timepicker-24').timepicker({
		            autoclose: true,
		            minuteStep: 5,
		            showSeconds: false,
		            showMeridian: false
		        });

		        // handle input group button click
				$container.find('.timepicker').parent('.input-group').on('click', '.input-group-btn', function(e){
		            e.preventDefault();
		            $(this).parent('.input-group').find('.timepicker').timepicker('showWidget');
		        });
		    }
		}
	};
	
	$.m.form.initDatePicker();
	
})(jQuery);